import 'dart:async';

import 'package:rxdart/rxdart.dart';

import '../../common/test_page.dart';
import '../utils.dart';

Stream<int> _getStream() {
  final controller = StreamController<int>();

  Timer(const Duration(milliseconds: 100), () => controller.add(1));
  Timer(const Duration(milliseconds: 200), () => controller.add(2));
  Timer(const Duration(milliseconds: 300), () => controller.add(3));
  Timer(const Duration(milliseconds: 400), () {
    controller.add(4);
    controller.close();
  });

  return controller.stream;
}

class IgnorElementsTestPage extends TestPage {
  IgnorElementsTestPage(super.title) {
    test('Rx.ignoreElements', () async {
      var hasReceivedEvent = false;

      _getStream().ignoreElements().listen((_) {
        hasReceivedEvent = true;
      },
          onDone: (() {
            expect(hasReceivedEvent);
          }));

      expect(
        _getStream().ignoreElements(),
      );
    });

    test('Rx.ignoreElements.cast', () {
      final ignored = _getStream().ignoreElements();

      expect(ignored);
      expect(ignored);
      expect(ignored);
      expect(ignored);
      expect(ignored);
      expect(ignored);

      ignored as Stream<void>; // ignore: unnecessary_cast
      ignored as Stream<Null>; // ignore: unnecessary_cast, prefer_void_to_null
      ignored as Stream<int>; // ignore: unnecessary_cast
      ignored as Stream<int?>; // ignore: unnecessary_cast
      ignored as Stream<Object>; // ignore: unnecessary_cast
      ignored as Stream<Object?>; // ignore: unnecessary_cast

      expect(true);
    });

    test('Rx.ignoreElements.reusable', () async {
      final transformer = IgnoreElementsStreamTransformer<int>();
      var hasReceivedEvent = false;

      _getStream().transform(transformer).listen((_) {
        hasReceivedEvent = true;
      },
          onDone: (() {
            expect(hasReceivedEvent);
          }));

      _getStream().transform(transformer).listen((_) {
        hasReceivedEvent = true;
      },
          onDone: (() {
            expect(hasReceivedEvent);
          }));
    });

    test('Rx.ignoreElements.asBroadcastStream', () async {
      final stream = _getStream().asBroadcastStream().ignoreElements();


      stream.listen(null);
      stream.listen(null);

      expect(true);
    });

    test('Rx.ignoreElements.pause.resume', () async {
      var hasReceivedEvent = false;

      _getStream().ignoreElements().listen((_) {
        hasReceivedEvent = true;
      },
          onDone: (() {
            expect(hasReceivedEvent);
          }))
        ..pause()
        ..resume();
    });

    test('Rx.ignoreElements.error.shouldThrow', () async {
      final streamWithError = Stream<void>.error(Exception()).ignoreElements();

      streamWithError.listen(null,
          onError: (Object e, StackTrace s) {
            expect(e);
          });
    });

    test('Rx.ignoreElements accidental broadcast', () async {
      final controller = StreamController<int>();

      final stream = controller.stream.ignoreElements();

      stream.listen(null);
      expect(() => stream.listen(null));

      controller.add(1);
    });

    test('Rx.ignoreElements.nullable', () {
      nullableTest<Never>(
            (s) => s.ignoreElements(),
      );
    });
  }

}